#include <iostream>
#include <vector>
#include <stdexcept>

class Matrix {
private:
    std::vector<std::vector<double>> data;
    int rows, cols;

public:
    // 构造函数
    Matrix(int row, int col) : rows(row), cols(col) {
        if (row <= 0 || col <= 0) {
            throw std::invalid_argument("Row and column sizes must be positive integers.");
        }
        data.resize(row, std::vector<double>(col));
    }

    // 访问元素
    double& operator()(int i, int j) {
        if (i < 0 || i >= rows || j < 0 || j >= cols) {
            throw std::out_of_range("Index out of range.");
        }
        return data[i][j];
    }

    // 输入运算符
    friend std::istream& operator>>(std::istream& is, Matrix& m) {
        for (int i = 0; i < m.rows; ++i) {
            for (int j = 0; j < m.cols; ++j) {
                is >> m.data[i][j];
            }
        }
        return is;
    }

    // 输出运算符
    friend std::ostream& operator<<(std::ostream& os, const Matrix& m) {
        for (int i = 0; i < m.rows; ++i) {
            for (int j = 0; j < m.cols; ++j) {
                os << m.data[i][j];
                if (j < m.cols - 1) os << " ";
            }
            if (i < m.rows - 1) os << "\n";
        }
        return os;
    }

    // 矩阵加法赋值运算
    Matrix& operator+=(const Matrix& other) {
        if (rows != other.rows || cols != other.cols) {
            throw std::invalid_argument("Matrices dimensions do not match for addition.");
        }
        for (int i = 0; i < rows; ++i) {
            for (int j = 0; j < cols; ++j) {
                data[i][j] += other.data[i][j];
            }
        }
        return *this;
    }

    // 矩阵乘法赋值运算
    Matrix& operator*=(const Matrix& other) {
        if (cols != other.rows) {
            throw std::invalid_argument("Matrices dimensions do not match for multiplication.");
        }
        Matrix result(rows, other.cols);
        for (int i = 0; i < rows; ++i) {
            for (int j = 0; j < other.cols; ++j) {
                result.data[i][j] = 0;
                for (int k = 0; k < cols; ++k) {
                    result.data[i][j] += data[i][k] * other.data[k][j];
                }
            }
        }
        data = result.data;
        rows = result.rows;
        cols = result.cols;
        return *this;
    }

    // 矩阵赋值运算
    Matrix& operator=(const Matrix& other) {
        if (this == &other) return *this;
        rows = other.rows;
        cols = other.cols;
        data = other.data;
        return *this;
    }
};

int main() {
    try {
        int row1, col1, row2, col2;
        std::cin >> row1 >> col1;
        Matrix table1(row1, col1);
        std::cin >> table1;

        std::cin >> row2 >> col2;
        Matrix table2(row2, col2);
        std::cin >> table2;

        // 输出 table1(row1/2, col1/2)
        std::cout << table1(row1 / 2, col1 / 2) << std::endl;

        // 判断并输出 table1 *= table2
        try {
            table1 *= table2;
            std::cout << table1 << std::endl;
        } catch (const std::invalid_argument& e) {
            std::cout << "ERROR!" << std::endl;
        }

        // 重置 table1
        Matrix temp1 = table1;

        // 判断并输出 table1 += table2
        try {
            temp1 += table2;
            std::cout << temp1 << std::endl;
        } catch (const std::invalid_argument& e) {
            std::cout << "ERROR!" << std::endl;
        }

        // 输出 table1 = table2
        table1 = table2;
        std::cout << table1 << std::endl;
    } catch (const std::exception& e) {
        std::cerr << e.what() << std::endl;
        return 1;
    }

    return 0;
}